<#--
List of variables to be passed for this template:
        +- rootPackage
        +- applicationName
        +- classNames
        +- directory
        +- Entities: ArrayList of EntityClass.getAsMap()

            |
            +- imports: imports
            |
            +- name: The name of the class.
            |    |
            |    +- single
            |    +- plural
            |
            +- idColumn: the id column
            |    |
            |    +- field
            |    |    |
            |    |    +- name
            |    |    +- type
            |    |
            |    +- getter
            |    +- setter
            |
            +- columns: ArrayList of columns
            |    |
            |    +- field
            |    |    |
            |    |    +- name
            |    |    +- type
            |    |    +- hasTypeParameter
            |    |    +- typeParameter -- only if hasTypeParameter returns true!
            |    +- getter
            |    +- setter

-->

<@pp.dropOutputFile />
<#list Entities as entity>
<@pp.changeOutputFile name="/development/${directory}/GWT/${directory}/client/apis/models/${entity.name.plural}.java" />

package ${rootPackage}.${applicationName}.client.apis.models;

import java.util.List;

import org.restlet.data.MediaType;
import billing.diag.client.apis.utils.JavaScriptArray;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class ${entity.name.plural} {

	private String url = Window.Location.getProtocol() + "//" + Window.Location.getHost() + "/diag/rest/${entity.name.plural}/";
        private String entityName = "${entity.name.single?uncap_first}";
        private String collectionEntityName = "${entity.name.plural?uncap_first}";

	public void find(String primaryKey, final AsyncCallback<${entity.name.single}> callback) {

		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL
				.encode(url + primaryKey + "/"));

		builder.setHeader("Accept", MediaType.APPLICATION_JSON.toString());

		try {
			Request request = builder.sendRequest(null, new RequestCallback() {
				public void onError(Request request, Throwable exception) {
					callback.onFailure(exception);
				}

				public void onResponseReceived(Request request,
						Response response) {
					if (200 == response.getStatusCode()) {
						JSONObject result = JSONParser
								.parse(response.getText()).isObject();
						callback.onSuccess((${entity.name.single}) result
								.getJavaScriptObject());
					} else {
						callback.onFailure(new Throwable(""
								+ response.getStatusCode() + ":"
								+ response.getStatusText()));
					}
				}
			});
		} catch (RequestException e) {
			callback.onFailure(e);
		}
	}

	public void list(int start, int max,
			final AsyncCallback<JavaScriptArray<${entity.name.single}>> callback) {

		RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL
				.encode(url + "?start=" + start + "&max=" + max));

		builder.setHeader("Accept", MediaType.APPLICATION_JSON.toString());

		try {
			Request request = builder.sendRequest(null, new RequestCallback() {
				public void onError(Request request, Throwable exception) {
					callback.onFailure(exception);
				}

				public void onResponseReceived(Request request,
						Response response) {
					if (200 == response.getStatusCode()) {
						JSONObject result = JSONParser
								.parse(response.getText()).isObject();
						JavaScriptArray<${entity.name.single}> entities = (JavaScriptArray<${entity.name.single}>) result
								.get(collectionEntityName).isArray()
								.getJavaScriptObject();
						callback.onSuccess(entities);
					} else {
						callback.onFailure(new Throwable(""
								+ response.getStatusCode() + ":"
								+ response.getStatusText()));
					}
				}
			});
		} catch (RequestException e) {
			callback.onFailure(e);
		}
	}


	public void merge(${entity.name.single} ${entity.name.single?uncap_first}, final AsyncCallback<${entity.name.single}> callback) {
		RequestBuilder builder = new RequestBuilder("PUT", URL.encode(url
				+ ${entity.name.single?uncap_first}.${entity.idColumn.getter}() + "/")) {
		};

		builder.setHeader("Content-Type", MediaType.APPLICATION_JSON.toString());

		try {

			JSONObject entity = new JSONObject();
			entity.put(entityName, new JSONObject(${entity.name.single?uncap_first}));

			Request request = builder.sendRequest(entity.toString(),
					new RequestCallback() {
						public void onError(Request request, Throwable exception) {
							callback.onFailure(exception);
						}

						public void onResponseReceived(Request request,
								Response response) {
							if (200 == response.getStatusCode()) {
								JSONObject result = JSONParser.parse(
										response.getText()).isObject();
								callback.onSuccess((${entity.name.single}) result
										.getJavaScriptObject());

							} else {
								callback.onFailure(new Throwable(response
										.getStatusCode()
										+ ": " + response.getStatusText()));
							}
						}
					});

		} catch (RequestException e) {
			callback.onFailure(e);
		}
	}

	public void persist(List<${entity.name.single}> ${entity.name.plural?uncap_first},
			final AsyncCallback<JavaScriptArray<${entity.name.single}>> callback) {
		RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL
				.encode(url));

		builder
				.setHeader("Content-Type", MediaType.APPLICATION_JSON
						.toString());

		try {
			JSONArray jsonArray = new JSONArray();
			for (int i = 0; i < ${entity.name.plural?uncap_first}.size(); i++) {
				jsonArray.set(i, new JSONObject(${entity.name.plural?uncap_first}.get(i)));
			}
			JSONObject entities1 = new JSONObject();
			entities1.put("@class", JSONParser.parse("\"list\""));
			entities1.put(entityName, jsonArray);

			JSONObject entities2 = new JSONObject();
			entities2.put(collectionEntityName, entities1);

			JSONObject entities = new JSONObject();
			entities.put(collectionEntityName, entities2);

			Request request = builder.sendRequest(entities.toString(),
					new RequestCallback() {
						public void onError(Request request, Throwable exception) {
							callback.onFailure(exception);
						}

						public void onResponseReceived(Request request,
								Response response) {
							if (200 == response.getStatusCode()) {
								JSONObject result = JSONParser.parse(
										response.getText()).isObject();
								JavaScriptArray<${entity.name.single}> entities = (JavaScriptArray<${entity.name.single}>) result
										.get(collectionEntityName).isArray()
										.getJavaScriptObject();
								callback.onSuccess(entities);
							} else {
								callback.onFailure(new Throwable(response
										.getStatusCode()
										+ ": " + response.getStatusText()));
							}
						}
					});

		} catch (RequestException e) {
			callback.onFailure(e);
		}
	}

	public void Delete(String primaryKey, final AsyncCallback<Void> callback) {

		RequestBuilder builder = new RequestBuilder("DELETE", URL.encode(url
				+ primaryKey + "/")) {
		};

		builder.setHeader("Accept", MediaType.APPLICATION_JSON.toString());

		try {
			Request request = builder.sendRequest(null, new RequestCallback() {
				public void onError(Request request, Throwable exception) {
					callback.onFailure(exception);
				}

				public void onResponseReceived(Request request,
						Response response) {
					if (200 == response.getStatusCode()) {
						callback.onSuccess(null);
					} else {
						callback.onFailure(new Throwable(""
								+ response.getStatusCode() + ":"
								+ response.getStatusText()));
					}
				}
			});
		} catch (RequestException e) {
			callback.onFailure(e);
		}
	}
}
</#list>